<!doctype html>
<html>
<head>
  <title>Dropbox JavaScript SDK</title>
  <link rel="stylesheet" href="/styles.css">
  <script src="https://cdn.bootcdn.net/ajax/libs/dropbox.js/9.8.6/Dropbox-sdk.min.js"></script></head>
<body>
<!-- Example layout boilerplate -->
<header class="page-header">
  <div class="container">
    <nav>
      <a href="/">
        <h1>
          <img src="https://cfl.dropboxstatic.com/static/images/brand/logotype_white-vflRG5Zd8.svg" class="logo" />
          JavaScript SDK Examples
        </h1>
      </a>
      <a href="https://github.com/dropbox/dropbox-sdk-js/tree/main/examples/javascript" class="view-source">View Source</a>
    </nav>
    <h2 class="code">
      <a href="/">examples</a> / upload file
    </h2>
  </div>
</header>

<!-- Example description and UI -->
<section class="container main">
  <p>This example shows how to use the <code>Dropbox.filesUpload()</code> [<a href="http://dropbox.github.io/dropbox-sdk-js/Dropbox.html#filesUpload">docs</a>] method to upload a file.</p>

  <form onSubmit="return uploadFile()">
    <input type="text" id="access-token" placeholder="Access token" />
    <input type="file" id="file-upload" />
    <button type="submit">Submit</button>
  </form>

  <!-- A place to show the status of the upload -->
  <h2 id="results"></h2>

  <p class="info">To obtain an access token for quick testing, you can go to <a href="https://dropbox.github.io/dropbox-api-v2-explorer/#files_list_folder" target="_blank">API Explorer</a> click the "Get Token" button on the top right, copy the token it creates and then paste it here.</p>
</section>

<script>
  function uploadFile() {

    const UPLOAD_FILE_SIZE_LIMIT = 150 * 1024 * 1024;
    var ACCESS_TOKEN = document.getElementById('access-token').value;
    var dbx = new Dropbox.Dropbox({ accessToken: ACCESS_TOKEN });
    var fileInput = document.getElementById('file-upload');
    var file = fileInput.files[0];


    if (file.size < UPLOAD_FILE_SIZE_LIMIT) { // File is smaller than 150 Mb - use filesUpload API
      dbx.filesUpload({path: '/' + file.name, contents: file})
        .then(function(response) {
          var results = document.getElementById('results');
          var br = document.createElement("br");
          results.appendChild(document.createTextNode('File uploaded!'));
          results.appendChild(br);
          console.log(response);
        })
        .catch(function(error) {
          console.table(error.error);
        });
    } else { // File is bigger than 150 Mb - use filesUploadSession* API
      const maxBlob = 8 * 1000 * 1000; // 8Mb - Dropbox JavaScript API suggested max file / chunk size

      var workItems = [];

      var offset = 0;

      while (offset < file.size) {
        var chunkSize = Math.min(maxBlob, file.size - offset);
        workItems.push(file.slice(offset, offset + chunkSize));
        offset += chunkSize;
      }

      const task = workItems.reduce((acc, blob, idx, items) => {
        if (idx == 0) {
          // Starting multipart upload of file
          return acc.then(function() {
            return dbx.filesUploadSessionStart({ close: false, contents: blob})
              .then(response => response.session_id)
          });
        } else if (idx < items.length-1) {
          // Append part to the upload session
          return acc.then(function(sessionId) {
            var cursor = { session_id: sessionId, offset: idx * maxBlob };
            return dbx.filesUploadSessionAppendV2({ cursor: cursor, close: false, contents: blob }).then(() => sessionId);
          });
        } else {
          // Last chunk of data, close session
          return acc.then(function(sessionId) {
            var cursor = { session_id: sessionId, offset: file.size - blob.size };
            var commit = { path: '/' + file.name, mode: 'add', autorename: true, mute: false };
            return dbx.filesUploadSessionFinish({ cursor: cursor, commit: commit, contents: blob });
          });
        }
      }, Promise.resolve());

      task.then(function(result) {
        var results = document.getElementById('results');
        results.appendChild(document.createTextNode('File uploaded!'));
      }).catch(function(error) {
        console.error(error);
      });

    }
    return false;
  }
</script>
</body>
</html>
